import sys
import time
import datetime
import can
import subprocess
from PyQt6 import QtCore, QtWidgets
from TimeSync.truly_car_timesync import Ui_Dialog  # 假设这个文件名为 truly_car_timesync.py


class CarTimeSyncApp(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self):
        super(CarTimeSyncApp, self).__init__()
        self.setupUi(self)

        # 连接按钮信号槽
        self.pushButton_2.clicked.connect(self.start_process)  # Start 按钮
        self.pushButton.clicked.connect(self.stop_process)  # Stop 按钮

        # 初始化定时器，用于定时发送CAN消息
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.send_can_message)

        # 停止按钮初始为不可用
        self.pushButton.setEnabled(False)

        # 初始化 CAN 通道
        self.can_channel = None

    def start_process(self):
        # 弹出输入密码的对话框
        password, ok = QtWidgets.QInputDialog.getText(self, "Input Password", "Enter sudo password:",
                                                      QtWidgets.QLineEdit.EchoMode.Password)

        # 如果用户点击确定，并且密码不为空
        if ok and password:
            # 禁用Start按钮，启用Stop按钮
            self.pushButton_2.setEnabled(False)
            self.pushButton.setEnabled(True)
            self.textEdit.append("Executing script with sudo...")

            # 使用subprocess执行外部脚本
            try:
                # 构建带密码的sudo命令
                command = "echo {} | sudo -E -S scripts/can_setup.sh".format(password)

                # 执行脚本并获取 can_channel 的值
                result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

                if result.returncode == 0:
                    self.textEdit.append("Script executed successfully.")

                    # 提取 can_channel
                    self.can_channel = self.extract_can_channel(result.stdout)
                    self.textEdit.append(f"can_channel: {self.can_channel}")
                    self.initialize_can_bus(self.can_channel)  # 传递 can_channel

                    self.start_sending_can()  # 开始发送CAN消息
                else:
                    self.textEdit.append(f"Script failed with error: {result.stderr}")
                    self.pushButton_2.setEnabled(True)
            except Exception as e:
                self.textEdit.append(f"Failed to execute script: {str(e)}")
                self.pushButton_2.setEnabled(True)
        else:
            self.textEdit.append("Password input cancelled or empty.")

    def extract_can_channel(self, script_output):
        """从脚本输出中提取 CAN 通道"""
        # 这里假设输出中包含 `can_channel=can0`
        for line in script_output.splitlines():
            if line.startswith("can_channel="):
                return line.split("=")[1].strip()
        return "vcan0"  # 默认值，如果未找到

    def initialize_can_bus(self, channel):
        """初始化CAN总线"""
        try:
            self.bus = can.interface.Bus(channel=channel, bustype='socketcan')
            self.textEdit.append(f"CAN bus '{channel}' initialized successfully.")
        except OSError as e:
            if "没有那个设备" in str(e):  # 检查错误信息
                self.textEdit.append("警告: CAN 设备不存在，继续运行程序。")
                self.bus = None  # 设置为 None 或其他适当的处理
            else:
                raise  # 重新抛出其他异常

    def start_sending_can(self):
        # 开启定时器，设置间隔为1秒（1000毫秒）
        self.timer.start(1000)
        self.textEdit.append("Started sending CAN messages.")

    def stop_process(self):
        # 停止发送CAN消息，停用定时器
        self.timer.stop()
        self.textEdit.append("Stopped sending CAN messages.")

        # 恢复Start按钮可点击，禁用Stop按钮
        self.pushButton_2.setEnabled(True)
        self.pushButton.setEnabled(False)

    def send_can_message(self):
        # 获取当前时间信号
        signals = self.get_current_time_signals()

        # 打包信号数据为CAN消息
        data = self.pack_message(signals)

        # 获取当前时间戳
        timestamp = time.time()

        # 构建CAN报文
        message = can.Message(arbitration_id=0x700, data=data, is_extended_id=False, timestamp=timestamp)

        try:
            self.bus.send(message)
            self.textEdit.append(f"Sent time info: {signals}")
            self.textEdit.append(f"Sent CAN message: {message}")
        except can.CanError as e:
            self.textEdit.append(f"CAN send error: {str(e)}")

    def get_current_time_signals(self):
        """从当前时间获取信号值"""
        now = datetime.datetime.now()  # 修正为 datetime.datetime.now()
        return {
            'CurrentTimeHour': now.hour,
            'CurrentTimeMinute': now.minute,
            'CurrentTimeSecond': now.second,
            'CurrentTimeMS': now.microsecond // 1000,  # 毫秒
            'CurrentTimeDay': now.day,
            'CurrentTimeMonth': now.month,
            'CurrentTimeYear': now.year - 2000  # 从2000开始
        }

    def pack_message(self, signals):
        """根据信号值将数据打包为CAN消息"""
        data = 0

        # 按位填充各个信号，以下是每个信号的位和长度
        data |= (signals['CurrentTimeHour'] & 0xFF)  # 7|8
        data |= (signals['CurrentTimeMinute'] & 0xFF) << 8  # 15|8
        data |= (signals['CurrentTimeSecond'] & 0x30) << 12  # 17|6
        data |= (signals['CurrentTimeSecond'] & 0x0F) << 28  # 17|6
        data |= (signals['CurrentTimeMS'] & 0x3FF) >> 8 << 24  # 25|10
        data |= (signals['CurrentTimeMS'] & 0xFF) << 32  # 25|10
        data |= (signals['CurrentTimeMonth'] & 0x0F) >> 3 << 40  # 40|4
        data |= (signals['CurrentTimeMonth'] & 0x07) << 53  # 40|4
        data |= (signals['CurrentTimeDay'] & 0x1F) << 41  # 45|5
        data |= ((signals['CurrentTimeYear'] & 0x7F) >> 2 << 48)  # 52|7
        data |= (signals['CurrentTimeYear'] & 0x03) << 62  # 52|7

        # 将64位数据拆分为8个字节
        data_bytes = data.to_bytes(8, byteorder='little')

        return data_bytes
